/*
 *    Copyright (c) 2018-2025, boss All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the boss developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: boss
 */
package com.hopes.bizz.poll.pollaqi.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hopes.bizz.common.core.util.DateUtils;
import com.hopes.bizz.poll.common.constant.MonitorConstant;
import com.hopes.bizz.poll.common.constant.OmConstant;
import com.hopes.bizz.poll.common.constant.PollFactorConstant;
import com.hopes.bizz.poll.factor.entity.PollFactorInfoEntity;
import com.hopes.bizz.poll.factor.service.PollFactorInfoService;
import com.hopes.bizz.poll.monitor.entity.PollMonitorSiteEntity;
import com.hopes.bizz.poll.monitor.service.PollMonitorSiteService;
import com.hopes.bizz.poll.om.dto.PollRtDataDTO;
import com.hopes.bizz.poll.om.entity.BaseOmDataEntity;
import com.hopes.bizz.poll.om.entity.PollHourEntity;
import com.hopes.bizz.poll.om.entity.PollMinEntity;
import com.hopes.bizz.poll.om.entity.PollRtDataHisEntity;
import com.hopes.bizz.poll.om.service.PollHourService;
import com.hopes.bizz.poll.om.service.PollMinService;
import com.hopes.bizz.poll.om.service.PollRtDataHisService;
import com.hopes.bizz.poll.pollaqi.entity.Aqi;
import com.hopes.bizz.poll.pollaqi.entity.PollAqiDataEntity;
import com.hopes.bizz.poll.pollaqi.entity.PollAqiEntity;
import com.hopes.bizz.poll.pollaqi.mapper.PollAqiDataMapper;
import com.hopes.bizz.poll.pollaqi.service.PollAqiDataService;
import com.hopes.bizz.poll.pollaqi.service.PollAqiService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * AQI指数
 *
 * @author ljh
 * @date 2023-06-06 15:03:00
 */
@Service
public class PollAqiDataServiceImpl extends ServiceImpl<PollAqiDataMapper, PollAqiDataEntity> implements PollAqiDataService {

    @Autowired
    private PollAqiService pollAqiService;
    @Autowired
    private PollMonitorSiteService pollMonitorSiteService;
    @Autowired
    private PollRtDataHisService pollRtDataHisService;
    @Autowired
    private PollFactorInfoService pollFactorInfoService;
    @Autowired
    private PollHourService pollHourService;
    @Autowired
    private PollMinService pollMinService;

    @Override
    public JSONObject getDayDate() {
        // 获取当月日期list
        List<String> timeList = DateUtils.getDayListOfMonth();
        LambdaQueryWrapper<PollAqiDataEntity> query = Wrappers.lambdaQuery();
        query.eq(PollAqiDataEntity::getDataType, OmConstant.DATA_TYPE_DAY);
        query.ge(PollAqiDataEntity::getDataTime, timeList.get(0)).le(PollAqiDataEntity::getDataTime, timeList.get(timeList.size() - 1));
        List<PollAqiDataEntity> pollAqiDataEntities = baseMapper.selectList(query);
        JSONObject res = new JSONObject();
        List<Integer> data = Stream.generate(() -> 0).limit(timeList.size()).collect(Collectors.toList());
        for (PollAqiDataEntity pollAqiDataEntity : pollAqiDataEntities) {
            int index = timeList.indexOf(pollAqiDataEntity.getDataTimeStr());
            data.set(index, pollAqiDataEntity.getDataJson().getJSONObject(OmConstant.AQI).getInteger(OmConstant.VAL));
        }
        res.put("time", timeList);
        res.put("data", data);
        res.put("AQIList", pollAqiService.list());
        return res;
    }


    @Override
    public Boolean calculateAQIMinHandler() {
        // 查询AQI站点
        LambdaQueryWrapper<PollMonitorSiteEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PollMonitorSiteEntity::getAqiFlag, MonitorConstant.IS_AQI_MONITOR);
        List<Long> monitorSiteList = pollMonitorSiteService.list(wrapper)
                .stream()
                .map(PollMonitorSiteEntity::getId)
                .distinct().collect(Collectors.toList());
        if (CollectionUtil.isEmpty(monitorSiteList)) {
            // 没有AQI站点直接返回
            return true;
        }
        Calendar cal = Calendar.getInstance();
        Date endTime = cal.getTime();
        cal.add(Calendar.MINUTE, -10);
        Date beginTime = cal.getTime();
        PollRtDataDTO pollRtDataDTO = new PollRtDataDTO();
        pollRtDataDTO.setBeginTime(beginTime);
        pollRtDataDTO.setEndTime(endTime);
        pollRtDataDTO.setIdList(monitorSiteList);
        List<PollRtDataHisEntity> pollRtDataHisEntities = pollRtDataHisService.queryByTimeAndMonitorList(pollRtDataDTO);
        if (CollectionUtil.isEmpty(pollRtDataHisEntities)){
            // 数据为空直接返回
            return true;
        }
        JSONObject sumO = new JSONObject();
        Double aqiValue = getAqiValue(pollRtDataHisEntities, sumO);

        // 保存数据
        saveAQI(sumO, aqiValue, new Date(), OmConstant.DATA_TYPE_MIN);

        return true;
    }

    public Boolean calculateAQIDayHandler() {
        // 查询AQI站点
        LambdaQueryWrapper<PollMonitorSiteEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PollMonitorSiteEntity::getAqiFlag, MonitorConstant.IS_AQI_MONITOR);
        List<Long> monitorSiteList = pollMonitorSiteService.list(wrapper)
                .stream()
                .map(PollMonitorSiteEntity::getId)
                .distinct().collect(Collectors.toList());
        if (CollectionUtil.isEmpty(monitorSiteList)) {
            // 没有AQI站点直接返回
            return true;
        }
        Calendar cal = Calendar.getInstance();
        Date endTime = cal.getTime();
        cal.add(Calendar.DAY_OF_YEAR, -1);
        Date beginTime = cal.getTime();
        PollRtDataDTO pollRtDataDTO = new PollRtDataDTO();
        pollRtDataDTO.setBeginTime(beginTime);
        pollRtDataDTO.setEndTime(endTime);
        pollRtDataDTO.setIdList(monitorSiteList);
        List<PollHourEntity> pollHourEntities = pollHourService.queryByTimeAndMonitorList(pollRtDataDTO);
        if (CollectionUtil.isEmpty(pollHourEntities)){
            // 数据为空直接返回
            return true;
        }
        JSONObject sumO = new JSONObject();
        Double aqiValue = getAqiValue(pollHourEntities, sumO);

        // 保存数据
        // 时
        cal.set(Calendar.HOUR_OF_DAY, 0);
        // 分
        cal.set(Calendar.MINUTE, 0);
        // 秒
        cal.set(Calendar.SECOND, 0);
        // 毫秒
        cal.set(Calendar.MILLISECOND, 0);
        saveAQI(sumO, aqiValue, cal.getTime(), OmConstant.DATA_TYPE_DAY);

        return true;
    }

    @Override
    public Boolean calculateAQIHourHandler() {
        // 查询AQI站点
        LambdaQueryWrapper<PollMonitorSiteEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PollMonitorSiteEntity::getAqiFlag, MonitorConstant.IS_AQI_MONITOR);
        List<Long> monitorSiteList = pollMonitorSiteService.list(wrapper)
                .stream()
                .map(PollMonitorSiteEntity::getId)
                .distinct().collect(Collectors.toList());
        if (CollectionUtil.isEmpty(monitorSiteList)) {
            // 没有AQI站点直接返回
            return true;
        }
        Calendar cal = Calendar.getInstance();
        Date endTime = cal.getTime();
        cal.add(Calendar.HOUR_OF_DAY, -1);
        Date beginTime = cal.getTime();
        PollRtDataDTO pollRtDataDTO = new PollRtDataDTO();
        pollRtDataDTO.setBeginTime(beginTime);
        pollRtDataDTO.setEndTime(endTime);
        pollRtDataDTO.setIdList(monitorSiteList);

        List<PollMinEntity> pollMinEntities = pollMinService.queryByTimeAndMonitorList(pollRtDataDTO);
        if (CollectionUtil.isEmpty(pollMinEntities)){
            // 数据为空直接返回
            return true;
        }
        JSONObject sumO = new JSONObject();
        Double aqiValue = getAqiValue(pollMinEntities, sumO);

        // 保存数据
        cal.setTime(endTime);
        cal.set(Calendar.MINUTE, 0);
        saveAQI(sumO, aqiValue, cal.getTime(), OmConstant.DATA_TYPE_HOUR);

        return true;
    }

    private void saveAQI(JSONObject sumO, Double aqiValue, Date time, Integer dataType) {
        // aqi值的范围
        LambdaQueryWrapper<PollAqiEntity> query = Wrappers.lambdaQuery();
        query.le(PollAqiEntity::getLeftVal, aqiValue)
                .ge(PollAqiEntity::getRightVal, aqiValue);
        PollAqiEntity aqiEntity = pollAqiService.getOne(query);

        // 保存AQI数据
        PollAqiDataEntity aqiData = new PollAqiDataEntity();
        aqiData.setDataType(dataType);
        aqiData.setDataTime(time);
        aqiData.setDataJson(sumO);
        aqiData.setName(aqiEntity.getName());
        aqiData.setLevel(aqiEntity.getLevel());
        aqiData.setColor(aqiEntity.getColor());
        aqiData.setLeftVal(aqiEntity.getLeftVal());
        aqiData.setRightVal(aqiEntity.getRightVal());
        baseMapper.insert(aqiData);
    }

    private Double getAqiValue(List<? extends BaseOmDataEntity> baseOmDataEntities, JSONObject sumO) {
        for (BaseOmDataEntity baseOmDataEntity : baseOmDataEntities) {
            JSONObject dataJson = baseOmDataEntity.getDataJson();
            // 只需要AQI计算需要的因子
            JSONObject data = new JSONObject();
            for (String s : PollFactorConstant.AQIcode) {
                data.put(s, dataJson.get(s));
            }
            pollRtDataHisService.handleCalculateAQITask(data, sumO, "val");
        }
        Map<String, PollFactorInfoEntity> map = pollFactorInfoService.list().stream().collect(Collectors.groupingBy(PollFactorInfoEntity::getCode,
                Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0))));
        // val求平均
        for (String s : sumO.keySet()) {
            JSONObject factorO = sumO.getJSONObject(s);
            double avg = factorO.getDoubleValue("val") / factorO.getDoubleValue("factorNum");
            factorO.put("val", Double.valueOf(String.format("%.2f", avg)));
            PollFactorInfoEntity pollFactorInfoEntity = map.get(s);
            if (ObjectUtil.isNotNull(pollFactorInfoEntity)) {
                factorO.put("name", Optional.ofNullable(pollFactorInfoEntity.getName()).orElse(""));
                factorO.put("unit", Optional.ofNullable(pollFactorInfoEntity.getUnit()).orElse(""));
            }

        }
        Aqi aqi = pollRtDataHisService.calculateAQI(sumO);
        JSONObject aqiO = new JSONObject();
        Double aqiValue = aqi.getAqi();
        aqiO.put("val", aqiValue);
        aqiO.put("name", "AQI");
        sumO.put("AQI", aqiO);
        return aqiValue;
    }
}
